import dash
from dash import dcc, html, Input, Output, State, MATCH, ALL
import dash_bootstrap_components as dbc
import random

# 预定义的单词列表
WORDS = {
    4: ["word", "game", "play", "test"],
    5: ["apple", "grape", "peach", "lemon"],
    6: ["banana", "orange", "tomato", "potato"]
}

# 随机选择一个单词
def choose_word(length):
    return random.choice(WORDS[length])

# 初始化 Dash 应用
app = dash.Dash(__name__, external_stylesheets=[dbc.themes.BOOTSTRAP])
app.config.suppress_callback_exceptions = True

app.layout = html.Div([
    # 上部功能区
    html.Div([
        html.H1("UNLIMITED WORDLY", style={'textAlign': 'center'}),
        dcc.Dropdown(
            id='word-length',
            options=[
                {'label': '4 Letters', 'value': 4},
                {'label': '5 Letters', 'value': 5},
                {'label': '6 Letters', 'value': 6}
            ],
            value=5,
            clearable=False,
            style={'width': '50%', 'margin': 'auto'}
        ),
    ], style={'textAlign': 'center', 'marginBottom': '20px'}),
    
    # 中间输入区
    html.Div(id='word-inputs', style={'textAlign': 'center', 'marginBottom': '20px'}),
    html.Button('Submit', id='submit-button', n_clicks=0, style={'display': 'block', 'margin': 'auto'}),
    html.Div(id='output', style={'textAlign': 'center', 'marginTop': '20px'}),
    
    # 下部键盘区
    html.Div(id='keyboard', children=[
        html.Div([
            html.Button(letter, id={'type': 'key', 'index': letter}, n_clicks=0, style={'margin': '5px'}) for letter in 'QWERTYUIOP'
        ], style={'textAlign': 'center'}),
        html.Div([
            html.Button(letter, id={'type': 'key', 'index': letter}, n_clicks=0, style={'margin': '5px'}) for letter in 'ASDFGHJKL'
        ], style={'textAlign': 'center'}),
        html.Div([
            html.Button('↵', id={'type': 'key', 'index': 'Enter'}, n_clicks=0, style={'margin': '5px'}),
            *[html.Button(letter, id={'type': 'key', 'index': letter}, n_clicks=0, style={'margin': '5px'}) for letter in 'ZXCVBNM'],
            html.Button('⌫', id={'type': 'key', 'index': 'Backspace'}, n_clicks=0, style={'margin': '5px'})
        ], style={'textAlign': 'center'}),
    ], style={'textAlign': 'center', 'marginTop': '20px'}),
    
    dcc.Store(id='word-store'),
    dcc.Store(id='attempts-store', data=0),
    dcc.Store(id='focus-store', data={'row': 0, 'col': 0})
])

@app.callback(
    Output('word-inputs', 'children'),
    Input('word-length', 'value')
)
def update_inputs(length):
    return html.Div([
        html.Div([
            dcc.Input(id={'type': 'input', 'index': f"{row}-{col}"}, type='text', 
                      maxLength=1, size='1', 
                      style={'width': '40px', 'height': '40px', 'textAlign': 'center', 'fontSize': '24px', 'margin': '5px'}) 
            for col in range(length)
        ], style={'display': 'block'}) for row in range(6)
    ], style={'display': 'block'})

@app.callback(
    Output('word-store', 'data'),
    Input('word-length', 'value')
)
def update_word(length):
    return choose_word(length)

@app.callback(
    Output('output', 'children'),
    Output('attempts-store', 'data'),
    Input('submit-button', 'n_clicks'),
    State('word-length', 'value'),
    State('word-store', 'data'),
    State('attempts-store', 'data'),
    State({'type': 'input', 'index': ALL}, 'value')
)
def check_word(n_clicks, length, word, attempts, inputs):
    if n_clicks == 0:
        return "", attempts

    if attempts >= 6:
        return "No more attempts left!", attempts

    # 过滤掉 None 值
    inputs = [i if i is not None else '' for i in inputs]
    guess = ''.join([inputs[i] for i in range(attempts * length, attempts * length + length)])
    if guess == word:
        return f"Correct! The word was {word}.", attempts + 1
    else:
        return f"Attempt {attempts + 1}: {guess} is incorrect.", attempts + 1

@app.callback(
    Output({'type': 'input', 'index': ALL}, 'value'),
    Input({'type': 'key', 'index': ALL}, 'n_clicks'),
    State({'type': 'input', 'index': ALL}, 'value'),
    State({'type': 'input', 'index': ALL}, 'id'),
    State('focus-store', 'data')
)
def update_input_from_keyboard(n_clicks, values, ids, focus):
    ctx = dash.callback_context
    if not ctx.triggered:
        return dash.no_update

    button_id = ctx.triggered[0]['prop_id'].split('.')[0]
    button_id = eval(button_id)  # 将字符串转换为字典
    key = button_id['index']

    if key == 'Enter' or key == 'Backspace':
        return dash.no_update

    row, col = focus['row'], focus['col']
    index = row * len(ids) // 6 + col

    if values[index] == '':
        values[index] = key
        return values

    return dash.no_update

@app.callback(
    Output('focus-store', 'data'),
    Input({'type': 'input', 'index': ALL}, 'value'),
    State('focus-store', 'data'),
    State('word-length', 'value')
)
def move_focus(value, focus, length):
    ctx = dash.callback_context
    if not ctx.triggered:
        return dash.no_update

    row, col = focus['row'], focus['col']
    next_col = col + 1
    next_row = row

    if next_col >= length:
        next_col = 0
        next_row += 1

    if next_row < 6:
        return {'row': next_row, 'col': next_col}

    return dash.no_update

if __name__ == '__main__':
    app.run_server(debug=True)
    
